<

Flutter アプリの国際化

アプリが別の言語を話すユーザーにデプロイされる可能性がある場合 言語を国際化する必要があります。 つまり、次のような方法でアプリを作成する必要があります。 テキストやレイアウトなどの値をローカライズすることが可能 アプリがサポートする言語またはロケールごとに。 Flutter は、次の作業に役立つウィジェットとクラスを提供します。 国際化と Flutter ライブラリ それ自体が国際化されています。

このページでは、以下に必要な概念とワークフローについて説明します。 を使用して Flutter アプリケーションをローカライズします。MaterialAppCupertinoAppクラス、 ほとんどのアプリがそのように書かれているからです。 ただし、下位レベルを使用して作成されたアプリケーションは、WidgetsAppクラスも国際化できる 同じクラスとロジックを使用します。

Flutter でのローカリゼーションの概要

このセクションでは、作成方法と 新しい Flutter アプリケーションを国際化する、 追加のセットアップとともに ターゲット プラットフォームで必要になる可能性があります。

この例のソース コードは次の場所にあります。gen_l10n_example

国際化アプリのセットアップ: Flutter_localizations パッケージ

デフォルトでは、Flutter は米国英語のローカリゼーションのみを提供します。 他の言語のサポートを追加するには、 アプリケーションは追加を指定する必要がありますMaterialApp(またCupertinoApp) プロパティ、 というパッケージを含めますflutter_localizations。 2023 年 6 月現在、このパッケージは以下をサポートしています。113の言語そして言語のバリエーション。

まず、新しい Flutter アプリケーションを作成します。 選択したディレクトリに、flutter create指図。

$ flutter create <name_of_flutter_app>

使用するにはflutter_localizations、 パッケージを依存関係として追加しますpubspec.yamlファイル、 同様にintlパッケージ:

$ flutter pub add flutter_localizations --sdk=flutter
$ flutter pub add intl:any

これにより、pubspec.yml次のエントリを含むファイル:

dependencies:
  flutter:
    sdk: flutter
  flutter_localizations:
    sdk: flutter
  intl: any

次に、インポートしますflutter_localizationsライブラリを指定してlocalizationsDelegatessupportedLocalesために あなたのMaterialAppまたCupertinoApp:

import 'package:flutter_localizations/flutter_localizations.dart';
return const MaterialApp(
  title: 'Localizations Sample App',
  localizationsDelegates: [
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
  supportedLocales: [
    Locale('en'), // English
    Locale('es'), // Spanish
  ],
  home: MyHomePage(),
);

導入後は、flutter_localizationsパッケージ 先ほどのコードを追加すると、 のMaterialCupertinoパッケージは正しくローカライズされるようになりました。 サポートされている 113 のロケールの 1 つ。 ウィジェットはローカライズされたメッセージに適応する必要があります。 正しい左から右または右から左のレイアウトとともに。

ターゲット プラットフォームのロケールを次のように切り替えてみます。 スペイン語 (es) メッセージはローカライズされる必要があります。

に基づくアプリWidgetsApp以外は似ていますが、GlobalMaterialLocalizations.delegate必要ありません。

完全なLocale.fromSubtagsコンストラクターが優先されます サポートするのでscriptCodeただし、Localeデフォルト コンストラクターはまだ完全に有効です。

の要素localizationsDelegatesリストは ローカライズされた値のコレクションを生成するファクトリー。GlobalMaterialLocalizations.delegateローカライズされたものを提供します マテリアルコンポーネントの文字列とその他の値 図書館。GlobalWidgetsLocalizations.delegateデフォルトのテキスト方向を定義します。 ウィジェット ライブラリの場合は、左から右または右から左のいずれかです。

これらのアプリのプロパティとその種類の詳細については、 Flutter アプリがどのように国際化されるかに依存します。 構造化されたものについては、このページで説明します。

ロケールをオーバーライドする

Localizations.override工場建設業者です のためにLocalizationsを可能にするウィジェット (通常はまれな) 状況では、アプリケーションのセクションが ロケールとは異なるロケールにローカライズする必要がある デバイスに合わせて設定されています。

この動作を観察するには、次の呼び出しを追加します。Localizations.overrideそして単純なCalendarDatePicker:

Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text(widget.title),
    ),
    body: Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          // Add the following code
          Localizations.override(
            context: context,
            locale: const Locale('es'),
            // Using a Builder to get the correct BuildContext.
            // Alternatively, you can create a new widget and Localizations.override
            // will pass the updated BuildContext to the new widget.
            child: Builder(
              builder: (context) {
                // A toy example for an internationalized Material widget.
                return CalendarDatePicker(
                  initialDate: DateTime.now(),
                  firstDate: DateTime(1900),
                  lastDate: DateTime(2100),
                  onDateChanged: (value) {},
                );
              },
            ),
          ),
        ],
      ),
    ),
  );
}

アプリをホットリロードすると、CalendarDatePickerウィジェットはスペイン語で再レンダリングされる必要があります。

独自のローカライズされたメッセージの追加

を追加した後、flutter_localizationsパッケージ、 ローカリゼーションを設定できます。 ローカライズされたテキストをアプリケーションに追加するには、 次の手順を完了します。

  1. を追加します。intl依存関係としてのパッケージ、プル によって固定されたバージョンではflutter_localizations:

    $ flutter pub add intl:any
    
  2. を開きますpubspec.yamlファイルを作成して有効にしますgenerate国旗。 このフラグは次の場所にあります。flutterpubspec ファイル内のセクション。

    # The following section is specific to Flutter.
    flutter:
      generate: true # Add this line
  3. 新しい yaml ファイルを Flutter プロジェクトのルート ディレクトリに追加します。 このファイルに名前を付けますl10n.yaml次のコンテンツが含まれます。

    eafa2909-0d7b-4def-8d2b​​-50507b7ecf9b

    このファイルはローカリゼーション ツールを構成します。 この例では、次のことを実行しました。

    • 置くアプリリソースバンドル(.arb) の入力ファイル${FLUTTER_PROJECT}/lib/l10n。 の.arbアプリのローカリゼーション リソースを提供します。
    • 英語のテンプレートを次のように設定しますapp_en.arb
    • Flutter にローカリゼーションを生成するように指示しました。app_localizations.dartファイル。
  4. ${FLUTTER_PROJECT}/lib/l10n、 を追加しますapp_en.arbテンプレートファイル。例えば:

    {
      "helloWorld": "Hello World!",
      "@helloWorld": {
        "description": "The conventional newborn programmer greeting"
      }
    }
  5. という名前の別のバンドル ファイルを追加します。app_es.arb同じディレクトリ内にあります。 このファイルに、同じメッセージのスペイン語翻訳を追加します。

    {
        "helloWorld": "¡Hola Mundo!"
    }
  6. さあ、走ってくださいflutter runコード生成は自動的に行われます。 生成されたファイルは次の場所にあるはずです。${FLUTTER_PROJECT}/.dart_tool/flutter_gen/gen_l10n。 あるいは、次のように実行することもできますflutter gen-l10nに アプリを実行せずに同じファイルを生成します。

  7. import ステートメントを追加しますapp_localizations.dartと10a2b898-8433-49fc-adc7-178786f​​49bf6コンストラクターへの呼び出しでMaterialApp:

    import 'package:flutter_gen/gen_l10n/app_localizations.dart';
    return const MaterialApp(
      title: 'Localizations Sample App',
      localizationsDelegates: [
        AppLocalizations.delegate, // Add this line
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: [
        Locale('en'), // English
        Locale('es'), // Spanish
      ],
      home: MyHomePage(),
    );

    AppLocalizationsクラスは自動生成も提供しますlocalizationsDelegatessupportedLocalesリスト。 これらを手動で提供する代わりに使用できます。

    const MaterialApp(
      title: 'Localizations Sample App',
      localizationsDelegates: AppLocalizations.localizationsDelegates,
      supportedLocales: AppLocalizations.supportedLocales,
    );
  8. 今すぐ使用できますAppLocalizationsアプリ内のどこでも:

    appBar: AppBar(
      // The [AppBar] title text should update its message
      // according to the system locale of the target platform.
      // Switching between English and Spanish locales should
      // cause this text to update.
      title: Text(AppLocalizations.of(context)!.helloWorld),
    ),

    このコードは、Text「Hello World!」を表示するウィジェット ターゲットデバイスのロケールが英語に設定されている場合、 そして「ホラ・ムンド!」ターゲットデバイスのロケールが設定されている場合 スペイン語に。の中にarbファイル、 各エントリのキーはゲッターのメソッド名として使用されます。 一方、そのエントリの値にはローカライズされたメッセージが含まれます。

gen_l10n_exampleはこのツールを使用します。

デバイスのアプリの説明をローカライズするには、 ローカライズされた文字列をに渡しますMaterialApp.onGenerateTitle:

return MaterialApp(
  onGenerateTitle: (context) => DemoLocalizations.of(context).title,

プレースホルダー、複数形、および選択

次のコマンドを使用して、メッセージにアプリケーション値を含めることもできます。 を使用する特別な構文プレースホルダーメソッドを生成するには ゲッターの代わりに。 プレースホルダー (有効な Dart 識別子名でなければなりません) 生成されたメソッドの位置パラメータになります。AppLocalizationsコード。ラップしてプレースホルダー名を定義する 次のように中括弧で囲みます。

"{placeholderName}"

各プレースホルダーを定義します。placeholders物体 アプリの中で.arbファイル。例えば、 hello メッセージを定義するには、userNameパラメータ、 以下を追加しますlib/l10n/app_en.arb:

"hello": "Hello {userName}",
"@hello": {
  "description": "A message with a single parameter",
  "placeholders": {
    "userName": {
      "type": "String",
      "example": "Bob"
    }
  }
}

このコード スニペットは、helloメソッド呼び出し のAppLocalizations.of(context)物体、 メソッドは次のタイプのパラメータを受け入れます。String; のhelloメソッドは文字列を返します。 を再生成しますAppLocalizationsファイル。

に渡されたコードを置き換えますBuilder以下のとおりです。

// Examples of internationalized strings.
return Column(
  children: <Widget>[
    // Returns 'Hello John'
    Text(AppLocalizations.of(context)!.hello('John')),
  ],
);

数値プレースホルダーを使用して複数の値を指定することもできます。 言語が異なれば、単語を複数形にする方法も異なります。 構文は次の指定もサポートしています。どうやって単語は複数形にする必要があります。 あ複数化されたメッセージには次のものが含まれている必要がありますnumパラメータを示す さまざまな状況で単語を複数形にする方法。 たとえば、英語では「person」を「people」と複数形にします。 しかしそれだけでは十分ではありません。 のmessage0複数形は「人がいない」または「人がいない」かもしれません。 のmessageFew複数かもしれない 「数人」、「何人か」、または「数人」。 のmessageMany複数の力 「ほとんどの人」、「多くの人」、または「群衆」。 より一般的なもののみmessageOtherフィールドは必須項目です。 次の例は、使用可能なオプションを示しています。

"{countPlaceholder, plural, =0{message0} =1{message1} =2{message2} few{messageFew} many{messageMany} other{messageOther}}"

前の式はメッセージのバリエーションに置き換えられます (message0message1, …) 値に対応する のcountPlaceholder。 だけmessageOtherフィールドは必須項目です。

次の例では、複数形のメッセージを定義しています。 「ウォンバット」という言葉:

"nWombats": "{count, plural, =0{no wombats} =1{1 wombat} other{{count} wombats}}",
"@nWombats": {
  "description": "A plural message",
  "placeholders": {
    "count": {
      "type": "num",
      "format": "compact"
    }
  }
}

を渡して複数のメソッドを使用します。countパラメータ:

// Examples of internationalized strings.
return Column(
  children: <Widget>[
    ...
    // Returns 'no wombats'
    Text(AppLocalizations.of(context)!.nWombats(0)),
    // Returns '1 wombat'
    Text(AppLocalizations.of(context)!.nWombats(1)),
    // Returns '5 wombats'
    Text(AppLocalizations.of(context)!.nWombats(5)),
  ],
);

複数形と同様に、 に基づいて値を選択することもできますStringプレースホルダー。 これは、性別言語をサポートするために最もよく使用されます。 構文は次のとおりです。

"{selectPlaceholder, select, case{message} ... other{messageOther}}"

次の例では、次のメッセージを定義しています。 性別に基づいて代名詞を選択します。

"pronoun": "{gender, select, male{he} female{she} other{they}}",
"@pronoun": {
  "description": "A gendered message",
  "placeholders": {
    "gender": {
      "type": "String"
    }
  }
}

この機能を使用するのは、 性別文字列をパラメータとして渡します。

// Examples of internationalized strings.
return Column(
  children: <Widget>[
    ...
    // Returns 'he'
    Text(AppLocalizations.of(context)!.pronoun('male')),
    // Returns 'she'
    Text(AppLocalizations.of(context)!.pronoun('female')),
    // Returns 'they'
    Text(AppLocalizations.of(context)!.pronoun('other')),
  ],
);

使用するときは次のことに注意してくださいselectステートメント、 パラメータと実際の値の比較 値では大文字と小文字が区別されます。 あれは、AppLocalizations.of(context)!.pronoun("Male")デフォルトは「other」の場合で、「they」を返します。

エスケープ構文

場合によってはトークンを使用する必要があります。 そのような{}、通常の文字として。 このようなトークンの解析を無視するには、 を有効にするuse-escapingを追加してフラグを立てます に続いてl10n.yaml:

use-escaping: true

パーサーは文字列を無視します 一対の一重引用符で囲みます。 通常の一重引用符文字を使用するには、 連続する一重引用符のペアを使用します。 たとえば、次のテキストは変換されます ダーツにString:

{
  "helloWorld": "Hello! '{Isn''t}' this a wonderful day?"
}

結果の文字列は次のようになります。

"Hello! {Isn't} this a wonderful day?"

数字と通貨を含むメッセージ

通貨の価値を表す数値を含む数値 ロケールが異なると表示方法が大きく異なります。 のローカリゼーション生成ツールflutter_localizationsを使用しますNumberFormatのクラスintlフォーマットするパッケージ ロケールと必要な形式に基づいて数値を指定します。

intdouble、 とnumberタイプはいずれかを使用できます 続くNumberFormatコンストラクター:

メッセージの「フォーマット」値 1200000の出力
compact 「1.2M」
compactCurrency* 「120万ドル」
compactSimpleCurrency* 「120万ドル」
compactLong "120万"
currency* 「1,200,000.00米ドル」
decimalPattern 「1,200,000」
decimalPercentPattern* 「120,000,000%」
percentPattern 「120,000,000%」
scientificPattern 「1E6」
simpleCurrency* 「120万ドル」

スター付きNumberFormatテーブル内のコンストラクター オプションの名前付きパラメータを提供します。 これらのパラメータは値として指定できます プレースホルダーのoptionalParameters物体。 たとえば、オプションのdecimalDigitsのパラメータcompactCurrency、 に次の変更を加えますlib/l10n/app_en.argファイル:

"numberOfDataPoints": "Number of data points: {value}",
"@numberOfDataPoints": {
  "description": "A message with a formatted int parameter",
  "placeholders": {
    "value": {
      "type": "int",
      "format": "compactCurrency",
      "optionalParameters": {
        "decimalDigits": 2
      }
    }
  }
}

日付付きのメッセージ

日付文字列はさまざまな方法でフォーマットされます ロケールとアプリのニーズの両方に応じて異なります。

タイプを含むプレースホルダー値DateTimeでフォーマットされていますDateFormatの中にintlパッケージ。

フォーマットバリエーションは41種類あり、 彼らの名前によって特定されるDateFormat工場の建設業者。 次の例では、DateTime価値 に登場するhelloWorldOnメッセージは でフォーマットされたDateFormat.yMd:

"helloWorldOn": "Hello World on {date}",
"@helloWorldOn": {
  "description": "A message with a date parameter",
  "placeholders": {
    "date": {
      "type": "DateTime",
      "format": "yMd"
    }
  }
}

ロケールが米国英語のアプリでは、 次の式は「7/9/1959」を生成します。 ロシアのロケールでは、「9.07.1959」が生成されます。

AppLocalizations.of(context).helloWorldOn(DateTime.utc(1959, 7, 9))

iOS 向けのローカライズ: iOS アプリ バンドルの更新

通常、iOS アプリケーションは主要なアプリケーション メタデータを定義します。 サポートされているロケールを含む、Info.plistファイル それはアプリケーションバンドルに組み込まれています。 アプリでサポートされているロケールを構成するには、 次の手順を使用してください。

  1. プロジェクトを開きますios/Runner.xcworkspaceXcode ファイル。

  2. の中にプロジェクトナビゲーターを開きます。Info.plistファイル 下RunnerプロジェクトのRunnerフォルダ。

  3. を選択情報プロパティリストアイテム。 次に選択しますアイテムの追加から編集者メニュー、 そして選択しますローカリゼーションポップアップメニューから。

  4. 新しく作成したものを選択して展開しますLocalizationsアイテム。 アプリケーションがサポートするロケールごとに、 新しい項目を追加し、追加するロケールを選択します のポップアップメニューから価値分野。 このリストは、リストされている言語と一致している必要があります。 の中にsupportedLocalesパラメータ。

  5. サポートされているロケールをすべて追加したら、ファイルを保存します。

さらにカスタマイズするための高度なトピック

このセクションでは、 ローカライズされた Flutter アプリケーション。

高度なロケール定義

複数のバリアントを持つ一部の言語では、単なる 適切に区別するための言語コード。

たとえば、のすべてのバリアントを完全に区別すると、 中国語では、言語コード、スクリプトコード、 そして国コード。これは存在のおかげです 簡体字と伝統的な文字、および地域の文字 同じスクリプトタイプ内での文字の書き方の違い。

中国語のあらゆるバリエーションを完全に表現するために、 国番号CNTW、 とHK、サポートされているリスト ロケールには以下を含める必要があります。

supportedLocales: [
  Locale.fromSubtags(languageCode: 'zh'), // generic Chinese 'zh'
  Locale.fromSubtags(
      languageCode: 'zh',
      scriptCode: 'Hans'), // generic simplified Chinese 'zh_Hans'
  Locale.fromSubtags(
      languageCode: 'zh',
      scriptCode: 'Hant'), // generic traditional Chinese 'zh_Hant'
  Locale.fromSubtags(
      languageCode: 'zh',
      scriptCode: 'Hans',
      countryCode: 'CN'), // 'zh_Hans_CN'
  Locale.fromSubtags(
      languageCode: 'zh',
      scriptCode: 'Hant',
      countryCode: 'TW'), // 'zh_Hant_TW'
  Locale.fromSubtags(
      languageCode: 'zh',
      scriptCode: 'Hant',
      countryCode: 'HK'), // 'zh_Hant_HK'
],

この明示的な完全な定義により、アプリは次のことが可能になります。 を区別し、完全に微妙なローカライズされた情報を提供します これらの国コードのすべての組み合わせにコンテンツを適用します。 ユーザーの優先ロケールが指定されていない場合、 Flutter は最も近い一致を選択します。 これには、ユーザーが期待するものとの違いが含まれる可能性があります。 Flutter は、で定義されたロケールにのみ解決されます。supportedLocalesローカライズされた scriptCode を提供します 一般的に使用される言語のコンテンツ。 見るLocalizationsサポート方法については、 ロケールと優先ロケールが解決されます。

中国語が代表的な例ですが、 フランス語などの他の言語 (fr_FRfr_CA) より微妙なローカリゼーションを行うには、完全に区別する必要もあります。

ロケールの追跡: Locale クラスと Localizations ウィジェット

Localeclass はユーザーの言語を識別します。 モバイル デバイスは、すべてのアプリケーションのロケール設定をサポートしています。 通常はシステム設定メニューを使用します。 国際化されたアプリは、次の値を表示することで応答します。 ロケール固有。たとえば、ユーザーがデバイスのロケールを切り替えた場合 英語からフランス語、そしてTextもともとあったウィジェット 表示された「Hello World」は「Bonjour le monde」で再構築されます。

Localizationsウィジェットはロケールを定義します その子と、その子が依存するローカライズされたリソースに対して。 のWidgetsAppウィジェットが作成するLocalizationsウィジェット システムのロケールが変更された場合は再構築します。

いつでもアプリの現在のロケールを検索できます。Localizations.localeOf():

Locale myLocale = Localizations.localeOf(context);

アプリのsupportedLocalesパラメータの指定

とはいえ、flutter_localizationsライブラリが現在サポートしている 113 の言語と言語バリアント (英語のみの翻訳) デフォルトで利用可能です。正確に決定するのは開発者次第です どの言語をサポートするか。

MaterialApp supportedLocalesパラメータはロケールの変更を制限します。ユーザーがロケールを変更したとき デバイスの設定、アプリのLocalizationsウィジェットのみ 新しいロケールがこのリストのメンバーである場合は、これに従います。 デバイスのロケールに完全に一致するものが見つからない場合は、 次に、一致する最初のサポートされるロケールlanguageCode使用されている。それが失敗した場合は、supportedLocalesリストが使用されます。

別の「ロケール解像度」を使用したいアプリ メソッドが提供できるのは、localeResolutionCallback。 たとえば、アプリに無条件に受け入れるようにするには ユーザーが選択したロケール:

MaterialApp(
  localeResolutionCallback: (
    locale,
    supportedLocales,
  ) {
    return locale;
  },
);

l10n.yaml ファイルの構成

l10n.yamlファイルを使用すると、gen-l10n道具 次のように指定します。

  • すべての入力ファイルが配置されている場所
  • すべての出力ファイルが作成される場所
  • ローカリゼーションデリゲートにどのような Dart クラス名を与えるか

オプションの完全なリストを表示するには、次のいずれかを実行しますflutter gen-l10n --helpコマンドラインで実行するか、次の表を参照してください。

オプション 説明
arb-dir テンプレートおよび翻訳された arb ファイルが配置されるディレクトリ。デフォルトはlib/l10n
output-dir 生成されたローカリゼーション クラスが書き込まれるディレクトリ。このオプションは、Flutter プロジェクト内の別の場所にローカリゼーション コードを生成する場合にのみ関係します。も設定する必要がありますsynthetic-packageフラグを false に設定します。

アプリは、で指定されたファイルをインポートする必要があります。output-localization-fileこのディレクトリからオプションを選択します。指定しない場合、デフォルトは、で指定された入力ディレクトリと同じディレクトリになります。arb-dir
template-arb-file Dart ローカリゼーション ファイルとメッセージ ファイルを生成するための基礎として使用されるテンプレート arb ファイル。デフォルトはapp_en.arb
output-localization-file 出力ローカリゼーションおよびローカリゼーションデリゲートクラスのファイル名。デフォルトはapp_localizations.dart
untranslated-messages-file ローカリゼーション メッセージを説明するファイルの場所はまだ翻訳されていません。このオプションを使用すると、ターゲットの場所に次の形式で JSON ファイルが作成されます。

"locale": ["message_1", "message_2" ... "message_n"]

このオプションが指定されていない場合、翻訳されていないメッセージの概要がコマンド ラインに出力されます。
output-class 出力ローカリゼーションおよびローカリゼーションデリゲートクラスに使用する Dart クラス名。デフォルトはAppLocalizations
preferred-supported-locales アプリケーションでサポートされている優先ロケールのリスト。デフォルトでは、ツールはサポートされているロケールのリストをアルファベット順に生成します。デフォルトで別のロケールを設定するには、このフラグを使用します。

たとえば、次のように渡します。[ en_US ]デバイスがサポートしている場合は、デフォルトでアメリカ英語が使用されます。
header 生成された Dart ローカリゼーション ファイルの先頭に追加するヘッダー。このオプションは文字列を受け取ります。

たとえば、次のように渡します。"/// All localized files."この文字列を生成された Dart ファイルの先頭に追加します。

または、以下をチェックしてください。header-file長いヘッダーのテキスト ファイルを渡すオプション。
header-file 生成された Dart ローカリゼーション ファイルの先頭に追加するヘッダー。このオプションの値は、生成された各 Dart ファイルの先頭に挿入されるヘッダー テキストを含むファイルの名前です。

または、以下をチェックしてください。headerより単純なヘッダーの文字列を渡すオプション。

このファイルは、で指定されたディレクトリに配置する必要があります。arb-dir
[no-]use-deferred-loading 遅延としてインポートされたロケールを使用して Dart ローカリゼーション ファイルを生成するかどうかを指定します。これにより、Flutter Web での各ロケールの遅延読み込みが可能になります。

これにより、JavaScript バンドルのサイズが小さくなり、Web アプリの初回起動時間を短縮できます。このフラグが true に設定されている場合、特定のロケールのメッセージは、必要な場合にのみ Flutter アプリによってダウンロードおよびロードされます。多くの異なるロケールと多くのローカライゼーション文字列を含むプロジェクトの場合、読み込みを延期することでパフォーマンスを向上させることができます。ロケールの数が少ないプロジェクトの場合、違いはごくわずかであり、ローカライズされた言語をバンドルする場合と比較して起動が遅くなる可能性があります。アプリケーションの残りの部分を続けます。

このフラグは、モバイルやデスクトップなどの他のプラットフォームには影響しないことに注意してください。
gen-inputs-and-outputs-list 指定すると、ツールはツールの入力と出力を含む JSON ファイルを生成します。gen_l10n_inputs_ and_outputs.json

これは、最新のローカリゼーション セットを生成するときに Flutter プロジェクトのどのファイルが使用されたかを追跡するのに役立ちます。たとえば、Flutter ツールのビルド システムはこのファイルを使用して、ホット リロード中に gen_l10n を呼び出すタイミングを追跡します。

このオプションの値は、JSON ファイルが生成されるディレクトリです。 null の場合、JSON ファイルは生成されません。
synthetic-package 生成された出力ファイルが合成パッケージとして生成されるか、Flutter プロジェクト内の指定されたディレクトリに生成されるかを決定します。この旗はtrueデフォルトでは。いつsynthetic-packageに設定されていますfalseで指定されたディレクトリにローカリゼーション ファイルが生成されます。arb-dirデフォルトでは。もしもoutput-dirを指定すると、そこにファイルが生成されます。
project-dir 指定すると、ツールはこのオプションに渡されたパスをルート Flutter プロジェクトのディレクトリとして使用します。

null の場合、現在の作業ディレクトリへの相対パスが使用されます。
[no-]required-resource-attributes すべてのリソース ID に、対応するリソース属性が含まれている必要があります。

デフォルトでは、単純なメッセージにはメタデータは必要ありませんが、読者にメッセージの意味のコンテキストを提供するため、メタデータを使用することを強くお勧めします。

複数のメッセージにはリソース属性が引き続き必要です。
[no-]nullable-getter ローカリゼーション クラスのゲッターが null 許容かどうかを指定します。

デフォルトでは、この値は true なので、Localizations.of(context)下位互換性のために null 許容値を返します。この値が false の場合、戻り値に対して null チェックが実行されます。Localizations.of(context)、ユーザーコードでの null チェックの必要性がなくなりました。
[no-]format 指定すると、dart formatコマンドはローカリゼーション ファイルの生成後に実行されます。
use-escaping エスケープ構文として一重引用符の使用を有効にするかどうかを指定します。
[no-]suppress-warnings 指定すると、すべての警告が抑制されます。

Flutter での国際化の仕組み

このセクションでは、ローカリゼーションの仕組みに関する技術的な詳細について説明します。 flutterで。独自のローカライズされたセットをサポートする予定がある場合は、 メッセージについては、次の内容が役立ちます。 それ以外の場合は、このセクションをスキップできます。

ローカライズされた値のロードと取得

Localizationsウィジェットは読み込みと ローカライズされた値のコレクションを含むオブジェクトを検索します。 アプリはこれらのオブジェクトを次のように参照します。Localizations.of(context,type)。 デバイスのロケールが変更されると、 のLocalizationsウィジェットは値を自動的にロードします 新しいロケールを設定し、それを使用したウィジェットを再構築します。 これが起こる理由は、Localizationsのように機能しますInheritedWidget。 ビルド関数が継承されたウィジェットを参照する場合、 継承されたウィジェットに対する暗黙的な依存関係が作成されます。 継承されたウィジェットが変更されたとき (そのときLocalizationsウィジェットのロケールが変更されます)、 依存するコンテキストが再構築されます。

ローカライズされた値は、Localizationsウィジェットの のリストLocalizationsDelegates. 各デリゲートは非同期を定義する必要がありますload()をカプセル化するオブジェクトを生成するメソッド ローカライズされた値のコレクション。 通常、これらのオブジェクトは、ローカライズされた値ごとに 1 つのメソッドを定義します。

大規模なアプリでは、さまざまなモジュールまたはパッケージがバンドルされる場合があります。 独自のローカリゼーション。だからこそ、Localizationsウィジェット オブジェクトのテーブルを 1 つずつ管理します。LocalizationsDelegate。 いずれかによって生成されたオブジェクトを取得するには、LocalizationsDelegateloadメソッド、を指定しますBuildContextそしてオブジェクトのタイプ。

例えば、 マテリアル コンポーネント ウィジェットのローカライズされた文字列 によって定義されますMaterialLocalizationsクラス。 このクラスのインスタンスは、LocalizationDelegateによって提供されるMaterialAppクラス。 それらは次のように取得できます。8bc28726-0d21-45ab-b265-fc5192467料金:

Localizations.of<MaterialLocalizations>(context, MaterialLocalizations);

この特定のLocalizations.of()という表現がよく使われますが、 それで、MaterialLocalizationsクラスは便利な省略表現を提供します。

static MaterialLocalizations of(BuildContext context) {
  return Localizations.of<MaterialLocalizations>(context, MaterialLocalizations);
}

/// References to the localized values defined by MaterialLocalizations
/// are typically written like this:

tooltip: MaterialLocalizations.of(context).backButtonTooltip,

アプリのローカライズされたリソースのクラスの定義

通常、国際化された Flutter アプリをまとめる アプリのローカライズされた値をカプセル化するクラスから始まります。 次の例は、そのようなクラスの典型的な例です。

の完全なソースコードintl_exampleこのアプリの場合。

この例は、intlパッケージ。のアプリの代替クラス ローカライズされたリソースセクション 説明します例それは依存しないintlパッケージ。

DemoLocalizationsクラス (次のコード スニペットで定義) アプリの文字列が含まれます (例として 1 つだけ) アプリがサポートするロケールに翻訳されます。 それは、initializeMessages()関数 ダーツによって生成されたintlパッケージ、Intl.message()、それらを調べます。

class DemoLocalizations {
  DemoLocalizations(this.localeName);

  static Future<DemoLocalizations> load(Locale locale) {
    final String name =
        locale.countryCode == null || locale.countryCode!.isEmpty
            ? locale.languageCode
            : locale.toString();
    final String localeName = Intl.canonicalizedLocale(name);

    return initializeMessages(localeName).then((_) {
      return DemoLocalizations(localeName);
    });
  }

  static DemoLocalizations of(BuildContext context) {
    return Localizations.of<DemoLocalizations>(context, DemoLocalizations)!;
  }

  final String localeName;

  String get title {
    return Intl.message(
      'Hello World',
      name: 'title',
      desc: 'Title for the Demo application',
      locale: localeName,
    );
  }
}

に基づいたクラスintlパッケージは生成されたものをインポートします を提供するメッセージ カタログinitializeMessages()関数とロケールごとのバッキング ストアfd1dd5c9-6b57-442a-83b5-1231e8​​32646a。 メッセージ カタログは、intl道具を含むクラスのソース コードを分析します。Intl.message()呼び出します。 この場合、それは単にDemoLocalizationsクラス。

新しい言語のサポートを追加する

に含まれていない言語をサポートする必要があるアプリGlobalMaterialLocalizations追加の作業を行う必要があります。 約 70 の翻訳 (「ローカリゼーション」) を提供する必要があります。 単語やフレーズ、日付のパターンや記号については、 ロケール。

追加方法の例については、以下を参照してください。 ノルウェー語ニーノシュク語のサポート。

新しいGlobalMaterialLocalizationsサブクラスは マテリアル ライブラリが依存するローカリゼーション。 新しいLocalizationsDelegateサービスを提供するサブクラス の工場としてGlobalMaterialLocalizationsサブクラス、 も定義する必要があります。

完全なソースコードは次のとおりですadd_language例、 実際のニーノシュク語の翻訳を差し引いたもの。

ロケール固有のGlobalMaterialLocalizationsサブクラス と呼ばれますNnMaterialLocalizations、 そしてそのLocalizationsDelegateサブクラスは_NnMaterialLocalizationsDelegate。 の値NnMaterialLocalizations.delegateはデリゲートのインスタンスであり、すべてです これは、これらのローカリゼーションを使用するアプリに必要です。

デリゲート クラスには、基本的な日付と数値の形式が含まれています ローカリゼーション。他のすべてのローカリゼーションは次のように定義されます。Stringの貴重なプロパティのゲッターNnMaterialLocalizations、 このような:

@override
String get moreButtonTooltip => r'More';

@override
String get aboutListTileTitleRaw => r'About $applicationName';

@override
String get alertDialogLabel => r'Alert';

もちろん、これらは英語の翻訳です。 ジョブを完了するには、リターンを変更する必要があります 各ゲッターの値を適切なニーノシュク文字列に変換します。

ゲッターは、次のような「生の」Dart 文字列を返します。r接頭語、 そのようなr'About $applicationName'、 場合によっては文字列に次の変数が含まれるためです。$接頭語。 変数は、パラメータ化されたローカリゼーション方法によって展開されます。

@override
String get pageRowsInfoTitleRaw => r'$firstRow–$lastRow of $rowCount';

@override
String get pageRowsInfoTitleApproximateRaw =>
    r'$firstRow–$lastRow of about $rowCount';

ロケールの日付パターンと記号も必要です。 ソースコード内で次のように定義されています。

const nnLocaleDatePatterns = {
  'd': 'd.',
  'E': 'ccc',
  'EEEE': 'cccc',
  'LLL': 'LLL',
  // ...
}
const nnDateSymbols = {
  'NAME': 'nn',
  'ERAS': <dynamic>[
    'f.Kr.',
    'e.Kr.',
  ],
  // ...
}

ロケールで正しい値が使用されるように、これらの値を変更する必要があります。 日付の書式設定。残念ながら、それ以来、intl図書館にはありません 数値の書式設定に関しても同じ柔軟性を共有し、 既存のロケールの書式設定を使用する必要があります の代わりとして_NnMaterialLocalizationsDelegate:

class _NnMaterialLocalizationsDelegate
    extends LocalizationsDelegate<MaterialLocalizations> {
  const _NnMaterialLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) => locale.languageCode == 'nn';

  @override
  Future<MaterialLocalizations> load(Locale locale) async {
    final String localeName = intl.Intl.canonicalizedLocale(locale.toString());

    // The locale (in this case `nn`) needs to be initialized into the custom
    // date symbols and patterns setup that Flutter uses.
    date_symbol_data_custom.initializeDateFormattingCustom(
      locale: localeName,
      patterns: nnLocaleDatePatterns,
      symbols: intl.DateSymbols.deserializeFromMap(nnDateSymbols),
    );

    return SynchronousFuture<MaterialLocalizations>(
      NnMaterialLocalizations(
        localeName: localeName,
        // The `intl` library's NumberFormat class is generated from CLDR data
        // (see https://github.com/dart-lang/i18n/blob/main/pkgs/intl/lib/number_symbols_data.dart).
        // Unfortunately, there is no way to use a locale that isn't defined in
        // this map and the only way to work around this is to use a listed
        // locale's NumberFormat symbols. So, here we use the number formats
        // for 'en_US' instead.
        decimalFormat: intl.NumberFormat('#,##0.###', 'en_US'),
        twoDigitZeroPaddedFormat: intl.NumberFormat('00', 'en_US'),
        // DateFormat here will use the symbols and patterns provided in the
        // `date_symbol_data_custom.initializeDateFormattingCustom` call above.
        // However, an alternative is to simply use a supported locale's
        // DateFormat symbols, similar to NumberFormat above.
        fullYearFormat: intl.DateFormat('y', localeName),
        compactDateFormat: intl.DateFormat('yMd', localeName),
        shortDateFormat: intl.DateFormat('yMMMd', localeName),
        mediumDateFormat: intl.DateFormat('EEE, MMM d', localeName),
        longDateFormat: intl.DateFormat('EEEE, MMMM d, y', localeName),
        yearMonthFormat: intl.DateFormat('MMMM y', localeName),
        shortMonthDayFormat: intl.DateFormat('MMM d'),
      ),
    );
  }

  @override
  bool shouldReload(_NnMaterialLocalizationsDelegate old) => false;
}

ローカリゼーション文字列の詳細については、 をチェックしてくださいflutter_localization の README。

言語固有のサブクラスを実装したら、GlobalMaterialLocalizationsLocalizationsDelegate、 言語とデリゲート インスタンスをアプリに追加する必要があります。 次のコードは、アプリの言語をニーノシュクに設定し、 を追加しますNnMaterialLocalizationsインスタンスをアプリに委任するlocalizationsDelegatesリスト:

const MaterialApp(
  localizationsDelegates: [
    GlobalWidgetsLocalizations.delegate,
    GlobalMaterialLocalizations.delegate,
    NnMaterialLocalizations.delegate, // Add the newly created delegate
  ],
  supportedLocales: [
    Locale('en', 'US'),
    Locale('nn'),
  ],
  home: Home(),
),

代替の国際化ワークフロー

このセクションでは、国際化するためのさまざまなアプローチについて説明します Flutter アプリケーション。

アプリのローカライズされたリソースの代替クラス

前の例は Dart に関して定義されました。intlパッケージ。独自の管理アプローチを選択できます 簡素化のため、または統合するためにローカライズされた値 別の i18n フレームワークを使用します。

の完全なソースコードminimalアプリ。

次の例では、DemoLocalizationsクラス すべての翻訳が言語ごとのマップに直接含まれています。

class DemoLocalizations {
  DemoLocalizations(this.locale);

  final Locale locale;

  static DemoLocalizations of(BuildContext context) {
    return Localizations.of<DemoLocalizations>(context, DemoLocalizations)!;
  }

  static const _localizedValues = <String, Map<String, String>>{
    'en': {
      'title': 'Hello World',
    },
    'es': {
      'title': 'Hola Mundo',
    },
  };

  static List<String> languages ()=> _localizedValues.keys.toList();

  String get title {
    return _localizedValues[locale.languageCode]!['title']!;
  }
}

最小限のアプリでは、DemoLocalizationsDelegateわずかに 違う。これはloadメソッドはSynchronousFuture非同期読み込みを行う必要がないためです。

class DemoLocalizationsDelegate
    extends LocalizationsDelegate<DemoLocalizations> {
  const DemoLocalizationsDelegate();

  @override
  bool isSupported(Locale locale) => DemoLocalizations.languages().contains(locale.languageCode);


  @override
  Future<DemoLocalizations> load(Locale locale) {
    // Returning a SynchronousFuture here because an async "load" operation
    // isn't needed to produce an instance of DemoLocalizations.
    return SynchronousFuture<DemoLocalizations>(DemoLocalizations(locale));
  }

  @override
  bool shouldReload(DemoLocalizationsDelegate old) => false;
}

Dart intl ツールの使用

Dart を使用して API を構築する前にintlパッケージ、 を見直すintlパッケージのドキュメント。 次のリストは、そのプロセスをまとめたものです。 に依存するアプリのローカライズintlパッケージ:

デモ アプリは、生成されたソース ファイルに依存します。l10n/messages_all.dart、すべてを定義します。 アプリで使用されるローカライズ可能な文字列。

再構築l10n/messages_all.dartには 2 つの手順が必要です。

  1. アプリのルートディレクトリをカレントディレクトリとして、 生成l10n/intl_messages.arbからlib/main.dart:

    $ dart run intl_translation:extract_to_arb --output-dir=lib/l10n lib/main.dart
    

    intl_messages.arbファイルは、1 つのエントリを含む JSON 形式のマップです。 各Intl.message()で定義された関数main.dart。 このファイルは、英語とスペイン語の翻訳のテンプレートとして機能します。intl_en.arbintl_es.arb。 これらの翻訳は開発者によって作成されます。

  2. アプリのルートディレクトリをカレントディレクトリとして、 生成intl_messages_<locale>.dartそれぞれにintl_<locale>.arbファイルとintl_messages_all.dart、 これにより、すべてのメッセージ ファイルがインポートされます。

    $ dart run intl_translation:generate_from_arb \
        --output-dir=lib/l10n --no-use-deferred-loading \
        lib/main.dart lib/l10n/intl_*.arb
    

    Windows はファイル名のワイルドカードをサポートしていません。代わりに、によって生成された .arb ファイルをリストします。intl_translation:extract_to_arb指図。

    $ dart run intl_translation:generate_from_arb \
        --output-dir=lib/l10n --no-use-deferred-loading \
        lib/main.dart \
        lib/l10n/intl_en.arb lib/l10n/intl_fr.arb lib/l10n/intl_messages.arb
    

    DemoLocalizationsクラスは生成されたものを使用しますinitializeMessages()関数 (で定義されています)intl_messages_all.dart) ローカライズされたメッセージをロードし、Intl.message()それらを調べるために。

詳しくは

コードを読むことが最もよく学ぶのであれば、 次の例を確認してください。

  • minimal
    minimal例は次のように設計されています できるだけシンプルに。
  • intl_example
    によって提供される API とツールを使用します。intlパッケージ。

ダーツならintlパッケージはあなたにとって新しいものですが、 チェックアウトDart intl ツールの使用